<!DOCTYPE html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/blog/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/blog/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/blog/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/blog/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/blog/images/favicon-new.jpg?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/blog/images/favicon-new.jpg?v=5.1.4">


  <link rel="mask-icon" href="/blog/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="JVM调优,JVM参数,JVM,">










<meta name="description" content="HotSpot JVM 提供了三类参数：  标准参数，标准参数中包括功能和输出的参数都是很稳定的，很可能在将来的JVM版本中不会改变。可以用java命令（或者是用 java -help）检索出所有标准参数，例如：-server。 X参数，非标准化的参数在将来的版本中可能会改变。所有的这类参数都以-X开始，并且可以用java -X来检索。 XX参数，同样不是标准的，然而在实际情况中，X参数和XX参数">
<meta name="keywords" content="JVM调优,JVM参数,JVM">
<meta property="og:type" content="article">
<meta property="og:title" content="JVM调优及实用参数">
<meta property="og:url" content="https://lenoy.gitee.io/blog/JVM_tuning_parameters.html">
<meta property="og:site_name" content="Lenoy聆羽">
<meta property="og:description" content="HotSpot JVM 提供了三类参数：  标准参数，标准参数中包括功能和输出的参数都是很稳定的，很可能在将来的JVM版本中不会改变。可以用java命令（或者是用 java -help）检索出所有标准参数，例如：-server。 X参数，非标准化的参数在将来的版本中可能会改变。所有的这类参数都以-X开始，并且可以用java -X来检索。 XX参数，同样不是标准的，然而在实际情况中，X参数和XX参数">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2021-11-12T09:46:52.620Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="JVM调优及实用参数">
<meta name="twitter:description" content="HotSpot JVM 提供了三类参数：  标准参数，标准参数中包括功能和输出的参数都是很稳定的，很可能在将来的JVM版本中不会改变。可以用java命令（或者是用 java -help）检索出所有标准参数，例如：-server。 X参数，非标准化的参数在将来的版本中可能会改变。所有的这类参数都以-X开始，并且可以用java -X来检索。 XX参数，同样不是标准的，然而在实际情况中，X参数和XX参数">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/blog/',
    scheme: 'Mist',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://lenoy.gitee.io/blog/JVM_tuning_parameters.html">





  <title>JVM调优及实用参数 | Lenoy聆羽</title>
  








</head>

<body itemscope="" itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope="" itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/blog/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Lenoy聆羽</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">刘超的个人博客，java开发工程师</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/blog/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/blog/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/blog/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br>
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup search-popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope="" itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://lenoy.gitee.io/blog/blog/JVM_tuning_parameters.html">

    <span hidden itemprop="author" itemscope="" itemtype="http://schema.org/Person">
      <meta itemprop="name" content="liuchao">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/blog/images/head.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope="" itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Lenoy聆羽">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">JVM调优及实用参数</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2020-09-12T00:00:00+08:00">
                2020-09-12
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope="" itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/JVM/" itemprop="url" rel="index">
                    <span itemprop="name">JVM</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>HotSpot JVM 提供了三类参数：</p>
<ul>
<li>标准参数，标准参数中包括功能和输出的参数都是很稳定的，很可能在将来的JVM版本中不会改变。可以用java命令（或者是用 java -help）检索出所有标准参数，例如：-server。</li>
<li>X参数，非标准化的参数在将来的版本中可能会改变。所有的这类参数都以-X开始，并且可以用java -X来检索。</li>
<li>XX参数，同样不是标准的，然而在实际情况中，X参数和XX参数并没有什么不同。X参数的功能是十分稳定的，然而很多XX参数仍在实验当中（主要是JVM的开发者用于debugging和调优JVM）。</li>
</ul>
<h4 id="XX-PrintFlagsFinal-and-XX-PrintFlagsInitial"><a href="#XX-PrintFlagsFinal-and-XX-PrintFlagsInitial" class="headerlink" title="-XX:+PrintFlagsFinal and -XX:+PrintFlagsInitial"></a>-XX:+PrintFlagsFinal and -XX:+PrintFlagsInitial</h4><p>通过<code>-XX:+PrintFlagsFinal</code>参数，可以输出所有XX参数和值：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">java -server -XX:+PrintFlagsFinal</span><br><span class="line">[Global flags]</span><br><span class="line">uintx AdaptivePermSizeWeight               = 20               &#123;product&#125;</span><br><span class="line">uintx AdaptiveSizeDecrementScaleFactor     = 4                &#123;product&#125;</span><br><span class="line">uintx AdaptiveSizeMajorGCDecayTimeScale    = 10               &#123;product&#125;</span><br><span class="line">uintx AdaptiveSizePausePolicy              = 0                &#123;product&#125;[...]</span><br><span class="line">uintx YoungGenerationSizeSupplementDecay   = 8                &#123;product&#125;</span><br><span class="line">uintx YoungPLABSize                        = 4096             &#123;product&#125;</span><br><span class="line"> bool ZeroTLAB                             = false            &#123;product&#125;</span><br><span class="line"> intx hashCode                             = 0                &#123;product&#125;</span><br></pre></td></tr></table></figure></p>
<p>第三列”=”表示第四列是参数的默认值，而”:=”表示参数被用户或者JVM赋值了。</p>
<p>通过<code>-XX:+PrintFlagsInitial</code>参数，可以所有XX参数的默认值。</p>
<h4 id="XX-PrintCommandLineFlags"><a href="#XX-PrintCommandLineFlags" class="headerlink" title="-XX:+PrintCommandLineFlags"></a>-XX:+PrintCommandLineFlags</h4><p>这个参数让JVM打印出那些已经被用户或者JVM设置过的详细的XX参数的名称和值。只列举出 <code>-XX:+PrintFlagsFinal</code>为”:=”的参数。以这种方式，我们可以用-XX:+PrintCommandLineFlags作为快捷方式来查看修改过的参数。<br>现在如果我们每次启动java 程序的时候设置 <code>-XX:+PrintCommandLineFlags</code> 并且输出到日志文件上，这样会记录下我们设置的JVM 参数对应用程序性能的影响。</p>
<p>此外，还可以使用jinfo命令显示启动的参数<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">jinfo -flags [pid] #查看目前启动使用的有效参数</span><br><span class="line">jinfo -flag [flagName] [pid] #查看对应参数的值</span><br></pre></td></tr></table></figure></p>
<p><strong>这里需要指出的是，当你配置jvm参数时，最好是先通过以上命令查看对应参数的默认值再确定是否需要设置。也最好不要配置你搞不清用途的参数，毕竟默认值的设置是有它的合理之处的。</strong></p>
<p><strong>动态设置参数</strong><br>Java应用启动后，定位到了是GC造成的性能问题，但是你启动的时候并没有加入打印gc的参数，很多时候的做法就是重新加参数然后重启应用。但这样会造成一定时间的服务不可用。最佳的做法是能够在不重启应用的情况下，动态设置参数。使用jinfo可以做到这一点(本质上还是基于jmx的)。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">jinfo -flag [+/-][flagName] [pid] #启用/禁止某个参数</span><br><span class="line">jinfo -flag [flagName=value] [pid] #设置某个参数</span><br></pre></td></tr></table></figure></p>
<p>比如可以使用以下命令打开heap dump并设置dump路径：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">jinfo -flag +HeapDumpBeforeFullGC [pid] </span><br><span class="line">jinfo -flag +HeapDumpAfterFullGC [pid]</span><br><span class="line">jinfo -flag HeapDumpPath=/home/dump/dir [pid]</span><br></pre></td></tr></table></figure></p>
<p>同样的也可以动态关闭：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">jinfo -flag -HeapDumpBeforeFullGC [pid] </span><br><span class="line">jinfo -flag -HeapDumpAfterFullGC [pid]</span><br></pre></td></tr></table></figure></p>
<h3 id="内存调优"><a href="#内存调优" class="headerlink" title="内存调优"></a>内存调优</h3><h4 id="Xms-and-Xmx-or-XX-InitialHeapSize-and-XX-MaxHeapSize"><a href="#Xms-and-Xmx-or-XX-InitialHeapSize-and-XX-MaxHeapSize" class="headerlink" title="-Xms and -Xmx (or: -XX:InitialHeapSize and -XX:MaxHeapSize)"></a>-Xms and -Xmx (or: -XX:InitialHeapSize and -XX:MaxHeapSize)</h4><p>-Xms和-Xmx可以说是最流行的JVM参数，它们可以允许我们指定JVM的初始和最大堆内存大小。一般来说，这两个参数的数值单位是Byte，但同时它们也支持使用速记符号，比如”k”或者”K”代表”kilo”，”m”或者”M”代表”mega”，”g”或者”G”代表”giga”。</p>
<h4 id="XX-HeapDumpOnOutOfMemoryError-and-XX-HeapDumpPath"><a href="#XX-HeapDumpOnOutOfMemoryError-and-XX-HeapDumpPath" class="headerlink" title="-XX:+HeapDumpOnOutOfMemoryError and -XX:HeapDumpPath"></a>-XX:+HeapDumpOnOutOfMemoryError and -XX:HeapDumpPath</h4><p>如果我们没法为-Xmx（最大堆内存）设置一个合适的大小，那么就有可能面临内存溢出（OutOfMemoryError）的风险，这可能是我们使用JVM时面临的最可怕的猛兽之一。<br>我们可以通过设置-XX:+HeapDumpOnOutOfMemoryError 让JVM在发生内存溢出时自动的生成堆内存快照。默认情况下，堆内存快照会保存在JVM的启动目录下名为java_pid<pid>.hprof 的文件里（在这里<pid>就是JVM进程的进程号）。也可以通过设置-XX:HeapDumpPath=<path>来改变默认的堆内存快照生成路径，<path>可以是相对或者绝对路径。</path></path></pid></pid></p>
<h4 id="XX-OnOutOfMemoryError"><a href="#XX-OnOutOfMemoryError" class="headerlink" title="-XX:OnOutOfMemoryError"></a>-XX:OnOutOfMemoryError</h4><p>当内存溢发生时，我们甚至可以可以执行一些指令，比如发个E-mail通知管理员或者执行一些清理工作。通过-XX:OnOutOfMemoryError 这个参数我们可以做到这一点，这个参数可以接受一串指令和它们的参数。在这里，我们将不会深入它的细节，但我们提供了它的一个例子。在下面的例子中，当内存溢出错误发生的时候，我们会将堆内存快照写到/tmp/heapdump.hprof 文件并且在JVM的运行目录执行脚本cleanup.sh。<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof -XX:OnOutOfMemoryError =<span class="string">"sh ~/cleanup.sh"</span> MyApp</span><br></pre></td></tr></table></figure></p>
<h4 id="XX-PermSize-and-XX-MaxPermSize"><a href="#XX-PermSize-and-XX-MaxPermSize" class="headerlink" title="-XX:PermSize and -XX:MaxPermSize"></a>-XX:PermSize and -XX:MaxPermSize</h4><p>-XX:MaxPermSize 用于设置永久代大小的最大值，-XX:PermSize 用于设置永久代初始大小。永久代在堆内存中是一块独立的区域，它包含了所有JVM加载的类的对象表示。为了成功运行应用程序，JVM会加载很多类（因为它们依赖于大量的第三方库，而这又依赖于更多的库并且需要从里面将类加载进来）这就需要增加永久代的大小。</p>
<h4 id="XX-InitialCodeCacheSize-and-XX-ReservedCodeCacheSize"><a href="#XX-InitialCodeCacheSize-and-XX-ReservedCodeCacheSize" class="headerlink" title="-XX:InitialCodeCacheSize and -XX:ReservedCodeCacheSize"></a>-XX:InitialCodeCacheSize and -XX:ReservedCodeCacheSize</h4><p>JVM一个有趣的，但往往被忽视的内存区域是“代码缓存”，它是用来存储已编译方法生成的本地代码。代码缓存确实很少引起性能问题，但是一旦发生其影响可能是毁灭性的。如果代码缓存被占满，JVM会打印出一条警告消息，并切换到interpreted-only 模式：JIT<br>编译器被停用，字节码将不再会被编译成机器码。因此，应用程序将继续运行，但运行速度会降低一个数量级，直到有人注意到这个问题。就像其他内存区域一样，我们可以自定义代码缓存的大小。相关的参数是 <strong>-XX:InitialCodeCacheSize</strong> 和 <strong>-XX:ReservedCodeCacheSize</strong>。</p>
<h4 id="XX-UseCodeCacheFlushing"><a href="#XX-UseCodeCacheFlushing" class="headerlink" title="-XX:+UseCodeCacheFlushing"></a>-XX:+UseCodeCacheFlushing</h4><p>如果代码缓存不断增长，例如，因为热部署引起的内存泄漏，那么提高代码的缓存大小只会延缓其发生溢出。为了避免这种情况的发生，我们可以尝试一个有趣的新参数：当代码缓存被填满时让JVM放弃一些编译代码。通过使用-XX:+UseCodeCacheFlushing 这个参数，我们至少可以避免当代码缓存被填满的时候JVM切换到interpreted-only 模式。</p>
<h3 id="新生代垃圾回收"><a href="#新生代垃圾回收" class="headerlink" title="新生代垃圾回收"></a>新生代垃圾回收</h3><p>单纯从JVM的功能考虑，并不需要新生代，完全可以针对整个堆进行操作。新生代存在的唯一理由是优化垃圾回收（GC）的性能。更具体说，<strong>把堆划分为新生代和老年代有2个好处：简化了新对象的分配（只在新生代分配内存），可以更有效的清除不再需要的对象（即死对象）</strong>（新生代和老年代使用不同的GC算法）。</p>
<p>通过广泛研究面向对象实现的应用，发现一个共同特点：<strong>很多对象的生存时间都很短</strong>。同时研究发现，<strong>新生对象很少引用生存时间长的对象</strong>。结合这2个特点，很明显 GC 会频繁访问新生对象，例如在堆中一个单独的区域，称之为新生代。在新生代中，GC可以快速标记回收“死对象”，而不需要扫描整个Heap中的存活一段时间的“老对象”。<br>SUN/Oracle 的HotSpot JVM 又把<strong>新生代进一步划分为3个区域</strong>：一个相对大点的区域，称为“伊甸园区(Eden)”；两个相对小点的区域称为“From 幸存区(survivor)”和“To 幸存区(survivor)”。按照规定，新对象会首先分配在 Eden 中（如果新对象过大，会直接分配在老年代中）。在GC中，Eden 中的对象会被移动到survivor中，直至对象满足一定的年纪(定义为熬过GC的次数),会被移动到老年代。</p>
<p><strong>新生代的GC使用复制算法</strong>。<br>在GC前 <strong>To 幸存区（survivor）</strong> 保持清空，对象保存在 <strong>Eden</strong> 和 <strong>From 幸存区（survivor）</strong> 中，GC运行时，<strong>Eden</strong> 中的幸存对象被复制到 <strong>To 幸存区（survivor）</strong>。针对 <strong>From 幸存区（survivor）</strong> 中的幸存对象，会考虑对象年龄，如果年龄没达到阀值（tenuring threshold），对象会被复制到<strong>To 幸存区（survivor<br>）</strong> 。如果达到阀值对象被复制到老年代。复制阶段完成后，<strong>Eden</strong> 和 <strong>From</strong> 幸存区中只保存死对象，可以视为清空。如果在复制过程中 <strong>To 幸存区</strong> 被填满了，剩余的对象会被复制到老年代中。最后 <strong>From 幸存区</strong> 和 <strong>To幸存区</strong> 会调换下名字，在下次GC时，<strong>To 幸存区</strong> 会成为 <strong>From 幸存区</strong> 。<br>对象一般出生在 <strong>Eden</strong> 区，年轻代GC过程中，对象在2个幸存区之间移动，如果对象存活到适当的年龄，会被移动到老年代。当对象在老年代死亡时，就需要更高级别的GC，更重量级的GC算法。<br>如果新生代过小，会导致新生对象很快就晋升到老年代中，在老年代中对象很难被回收。如果新生代过大，会发生过多的复制过程。我们需要找到一个合适大小，要想获得一个合适的大小，只能通过不断的测试调优。这个时候就需要JVM参数了。</p>
<h4 id="Xmn"><a href="#Xmn" class="headerlink" title="-Xmn"></a>-Xmn</h4><p>设置年轻代大小。整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m，所以增大年轻代后，将会减小年老代大小。此值对系统性能影响较大，Sun官方推荐配置为整个堆的3/8。</p>
<h4 id="XX-NewSize-and-XX-MaxNewSize"><a href="#XX-NewSize-and-XX-MaxNewSize" class="headerlink" title="-XX:NewSize and -XX:MaxNewSize"></a>-XX:NewSize and -XX:MaxNewSize</h4><p>设置 <strong>-XX:MaxNewSize</strong> 参数时，应该考虑到新生代只是整个堆的一部分，新生代设置的越大，老年代区域就会减少。一般不允许新生代比老年代还大，因为要考虑GC时最坏情况，所有对象都晋升到老年代，<strong>-XX:MaxNewSize</strong> 最大可以设置为 <strong>-Xmx/2</strong>。考虑性能，一般会通过参数 <strong>-XX:NewSize</strong> 设置新生代初始大小。如果知道新生代初始分配的对象大小(经过监控) ，这样设置会有帮助，可以节省新生代自动扩展的消耗。</p>
<h4 id="XX-NewRatio"><a href="#XX-NewRatio" class="headerlink" title="-XX:NewRatio"></a>-XX:NewRatio</h4><p>可以设置新生代和老年代的相对大小。这种方式的优点是新生代大小会随着整个堆大小动态扩展。参数 <strong>-XX:NewRatio</strong> 设置老年代与新生代的比例。例如 <strong>-XX:NewRatio=3</strong> 指定老年代/新生代为3/1。老年代占堆大小的 3/4 ，新生代占 1/4 。如果针对新生代，同时定义绝对值和相对值，绝对值将起作用。</p>
<p>在设置新生代大小问题上，使用绝对值还是相对值，不存在通用准则 。如果了解应用的内存使用情况,设置固定大小的堆和新生代更有利，当然也可以设置相对值。如果对应用的内存使用一无所知，正确的做法是不要设置任何参数。如果遇到性能或OutOfMemoryErrors，在调优之前，首先需要进行一系列有目的的监控测试，缩小问题的根源。</p>
<h4 id="XX-SurvivorRatio"><a href="#XX-SurvivorRatio" class="headerlink" title="-XX:SurvivorRatio"></a>-XX:SurvivorRatio</h4><p>-XX:SurvivorRatio 指定伊甸园区（Eden）与幸存区大小比例。例如，<strong>-XX:SurvivorRatio=10</strong> 表示伊甸园区（Eden）是 幸存区To 大小的10倍（也是幸存区From的10倍)。所以，甸园区（Eden)占新生代大小的10/12，幸存区From和幸存区To 每个占新生代的1/12 。注意，两个幸存区永远是一样大的。<br>我们希望最小化短命对象晋升到老年代的数量，同时也希望最小化新生代GC 的次数和持续时间。我们需要找到针对当前应用的折中方案，寻找适合方案的起点是了解当前应用中对象的年龄分布情况。</p>
<h4 id="XX-PrintTenuringDistribution"><a href="#XX-PrintTenuringDistribution" class="headerlink" title="-XX:+PrintTenuringDistribution"></a>-XX:+PrintTenuringDistribution</h4><p>参数 <strong>-XX:+PrintTenuringDistribution</strong> 指定JVM 在每次新生代GC时，输出幸存区中对象的年龄分布。例如：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Desired survivor size 75497472 bytes, new threshold 15 (max 15)</span><br><span class="line">- age 1: 19321624 bytes, 19321624 total</span><br><span class="line">- age 2: 79376 bytes, 19401000 total</span><br><span class="line">- age 3: 2904256 bytes, 22305256 total</span><br></pre></td></tr></table></figure></p>
<p>第一行说明幸存区To大小为 75 MB，老年代阀值为15，最大也是15。之后行表示，对于小于老年代阀值的每一个对象年龄,本年龄中对象所占字节（如果当前年龄没有对象,这一行会忽略）。上例中，一次 GC 后幸存对象大约 19 MB，两次GC 后幸存对象大约79 KB，三次GC 后幸存对象大约 3 MB。每行结尾，显示直到本年龄全部对象大小。所以，最后一行的 total 表示幸存区To 总共被占用22 MB。</p>
<h4 id="XX-InitialTenuringThreshold-XX-MaxTenuringThreshold-and-XX-TargetSurvivorRatio"><a href="#XX-InitialTenuringThreshold-XX-MaxTenuringThreshold-and-XX-TargetSurvivorRatio" class="headerlink" title="-XX:InitialTenuringThreshold, -XX:MaxTenuringThreshold and -XX:TargetSurvivorRatio"></a>-XX:InitialTenuringThreshold, -XX:MaxTenuringThreshold and -XX:TargetSurvivorRatio</h4><p>通过 <strong>-XX:InitialTenuringThreshold</strong> 和 <strong>-XX:MaxTenuringThreshold</strong> 可以设定老年代阀值的初始值和最大值。另外，可以通过参数 <strong>-XX:TargetSurvivorRatio</strong> 设定幸存区的目标使用率。例如， <strong>-XX:TargetSurvivorRatio=90</strong> 设定老年代阀值的上限为10，幸存区空间目标使用率为90%。<br>如果从年龄分布中发现，在到达老年代阀值之前，有很多对象的年龄持续增长，这表示 <strong>-XX:MaxTenuringThreshold</strong> 设置过大。如果 <strong>-XX:MaxTenuringThreshold</strong> 的值大于1，但是很多对象年龄从未大于1，应该看下幸存区的目标使用率。如果幸存区使用率从未到达，这表示对象都被GC回收，这正是我们想要的。如果幸存区使用率经常达到，有些年龄超过1的对象被移动到老年代中。这种情况，可以尝试调整幸存区大小或目标使用率。</p>
<h4 id="XX-NeverTenure-and-XX-AlwaysTenure"><a href="#XX-NeverTenure-and-XX-AlwaysTenure" class="headerlink" title="-XX:+NeverTenure and -XX:+AlwaysTenure"></a>-XX:+NeverTenure and -XX:+AlwaysTenure</h4><p>设置参数 <strong>-XX:+NeverTenure</strong> , 对象永远不会晋升到老年代。当我们确定不需要老年代时，可以这样设置。这样设置风险很大，并且会浪费至少一半的堆内存。相反设置参数 <strong>-XX:+AlwaysTenure</strong>，表示没有幸存区，所有对象在第一次GC时，会晋升到老年代。<br>一般情况下，没有合理的场景使用这个参数。</p>
<h3 id="指定垃圾收集器"><a href="#指定垃圾收集器" class="headerlink" title="指定垃圾收集器"></a>指定垃圾收集器</h3><p>评估一个垃圾收集(GC)算法如何根据如下两个标准：</p>
<ul>
<li>吞吐量越高算法越好</li>
<li>暂停时间越短算法越好</li>
</ul>
<p>JVM在专门的线程（GC threads）中执行GC。 只要GC线程是活动的，它们将与应用程序线程（application threads）争用当前可用CPU的时钟周期。 简单点来说，吞吐量是指应用程序线程用时占程序总用时的比例。 例如，吞吐量99/100意味着100秒的程序执行时间应用程序线程运行了99秒， 而在这一时间段内GC线程只运行了1秒。</p>
<p><strong>暂停时间</strong> 是指一个时间段内应用程序线程让与GC线程执行而完全暂停。 例如，GC期间100毫秒的暂停时间意味着在这100毫秒期间内没有应用程序线程是活动的。 如果说一个正在运行的应用程序有100毫秒的“平均暂停时间”，那么就是说该应用程序所有的暂停时间平均长度为100毫秒。</p>
<h4 id="XX-UseSerialGC"><a href="#XX-UseSerialGC" class="headerlink" title="-XX:+UseSerialGC"></a>-XX:+UseSerialGC</h4><p>使用该标志来激活串行垃圾收集器，例如单线程面向吞吐量垃圾收集器。无论年轻代还是年老代都将只有一个线程执行垃圾收集，用于只有单个可用处理器核心的JVM。</p>
<h4 id="XX-UseParallelGC"><a href="#XX-UseParallelGC" class="headerlink" title="-XX:+UseParallelGC"></a>-XX:+UseParallelGC</h4><p>使用这个标志告诉JVM使用多线程并行执行年轻代垃圾收集。</p>
<h4 id="XX-UseParallelOldGC"><a href="#XX-UseParallelOldGC" class="headerlink" title="-XX:+UseParallelOldGC"></a>-XX:+UseParallelOldGC</h4><p>除了激活年轻代并行垃圾收集，也激活了年老代并行垃圾收集。当期望高吞吐量，并且JVM有两个或更多可用处理器核心时，建议使用该标志。</p>
<h4 id="XX-ParallelGCThreads"><a href="#XX-ParallelGCThreads" class="headerlink" title="-XX:ParallelGCThreads"></a>-XX:ParallelGCThreads</h4><p>通过 <strong>-XX:ParallelGCThreads=<value></value></strong> 我们可以指定并行垃圾收集的线程数量，如果不明确设置该标志，虚拟机将使用基于可用(虚拟)处理器数量计算的默认值。 决定因素是由<code>Java Runtime.availableProcessors()</code>方法的返回值N，如果N&lt;=8，并行垃圾收集器将使用N个垃圾收集线程，如果N&gt;8，垃圾收集线程数量应为3+5N/8。当JVM独占地使用系统和处理器时使用默认设置更有意义。 但是，如果有多个JVM(或其他耗CPU的系统)在同一台机器上运行，我们应该使用 <strong>-XX:ParallelGCThreads</strong> 来减少垃圾收集线程数到一个适当的值。</p>
<h4 id="并行收集器设置"><a href="#并行收集器设置" class="headerlink" title="并行收集器设置"></a>并行收集器设置</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数</span><br><span class="line">-XX:MaxGCPauseMillis=n:设置并行收集最大的暂停时间（如果到这个时间了，垃圾回收器依然没有回收完，也会停止回收）</span><br><span class="line">-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为：1/(1+n)</span><br><span class="line">-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况</span><br><span class="line">-XX:ParallelGCThreads=n:设置并发收集器年轻代手机方式为并行收集时，使用的CPU数。并行收集线程数</span><br></pre></td></tr></table></figure>
<h4 id="XX-GCTimeRatio"><a href="#XX-GCTimeRatio" class="headerlink" title="-XX:GCTimeRatio"></a>-XX:GCTimeRatio</h4><p>通过 <strong>-XX:GCTimeRatio=<value></value></strong> 我们告诉JVM吞吐量要达到的目标值。更准确地说，<strong>-XX:GCTimeRatio=N</strong> 指定目标应用程序线程的执行时间(与总的程序执行时间)达到N/(N+1)的目标比值。 例如，通过 <strong>-XX:GCTimeRatio=9</strong> 我们要求应用程序线程在整个执行时间中至少9/10是活动的(因此，GC线程占用其余1/10)。 </p>
<h4 id="XX-MaxGCPauseMillis"><a href="#XX-MaxGCPauseMillis" class="headerlink" title="-XX:MaxGCPauseMillis"></a>-XX:MaxGCPauseMillis</h4><p>通过 <strong>-XX:GCTimeRatio=<value></value></strong> 告诉JVM最大暂停时间的目标值(以毫秒为单位)。当设置最大暂停时间目标时，不要选择太小的值。 因为为了保持低暂停时间，JVM需要增加GC次数，那样可能会严重影响可达到的吞吐量。对于要求低暂停时间作为主要目标的应用程序(大多数是Web应用程序)，建议不要使用吞吐量收集器，而是选择CMS收集器。</p>
<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><h4 id="年轻代大小选择"><a href="#年轻代大小选择" class="headerlink" title="年轻代大小选择"></a>年轻代大小选择</h4><p>响应时间优先的应用：尽可能设置大，直到接近系统的最低响应时间限制（根据实际情况选择）。在此种情况下，年轻代收集发生的频率也是最小的。同时减少到达年老代的对象。<br>吞吐量优先的应用：尽可能的设置大，可能到达Gbit的成都，因为对响应时间没有要求，垃圾收集可以并行进行，一般适合8核CPU以上应用。</p>
<h4 id="年老代大小选择"><a href="#年老代大小选择" class="headerlink" title="年老代大小选择"></a>年老代大小选择</h4><h5 id="响应时间优先的应用"><a href="#响应时间优先的应用" class="headerlink" title="响应时间优先的应用"></a>响应时间优先的应用</h5><p>年老代使用并发收集器，所以其大小需要小心设置，一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了，可能会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式；如果堆大了，则需要较长的收集时间。最优化的方案，一般需要参考一下数据获得：</p>
<ol>
<li>并发垃圾收集信息</li>
<li>持久代并发收集次数</li>
<li>传统GC信息</li>
<li>花在年轻代和年老代回收上的时间比例减少年轻代和年老代花费的时间，一般会提高应用的效率</li>
</ol>
<h5 id="吞吐量优先的应用"><a href="#吞吐量优先的应用" class="headerlink" title="吞吐量优先的应用"></a>吞吐量优先的应用</h5><p>一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是，这样可以尽可能回收掉大部分短期对象，减少中期对象，而年老代尽存放长期存活的对象。</p>
<h5 id="较小堆引起的碎片问题"><a href="#较小堆引起的碎片问题" class="headerlink" title="较小堆引起的碎片问题"></a>较小堆引起的碎片问题</h5><p>因为年老代的并发收集器使用标记、清除算法，所以不会对堆进行压缩。当收集器回收时，他会把相邻的空间进行合并，这样可以分配给较大的对象。但是当堆空间较小时，运行一段时间以后，就会出现“碎片”，如果并发收集器找不到足够的空间，那么并发收集器将会停止，然后使用传统的标记、清除方式进行回收。如果出现“碎片”，可能需要进行如下配置：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">-XX:+UseCMSCompactAtFullCollection:使用并发收集器时，开启对年老代的压缩</span><br><span class="line">-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下，这里设置多少次FullGc后，对年老代进行压缩</span><br></pre></td></tr></table></figure></p>

      
    </div>
    
    
    
    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:16px;">--------------<i class="fa fa-paw"></i>本文结束<i class="fa fa-paw"></i>--------------</div>
    
</div>
      
    </div>
    

    
      <div>
        <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
  <div>觉得文章不错就打赏一下哟~~~</div>
  <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
    <span>打赏</span>
  </button>
  <div id="QR" style="display: none;">

    
      <div id="wechat" style="display: inline-block">
        <img id="wechat_qr" src="/blog/images/wechatpay.png" alt="liuchao 微信支付">
        <p>微信支付</p>
      </div>
    

    
      <div id="alipay" style="display: inline-block">
        <img id="alipay_qr" src="/blog/images/alipay.png" alt="liuchao 支付宝">
        <p>支付宝</p>
      </div>
    

    

  </div>
</div>

      </div>
    

    
      <div>
        <ul class="post-copyright">
<!--
  <li class="post-copyright-author">
    <strong>本文作者：</strong>
    liuchao
  </li>
-->
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://lenoy.gitee.io/blog/JVM_tuning_parameters.html" title="JVM调优及实用参数">https://lenoy.gitee.io/blog/JVM_tuning_parameters.html</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>
    本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/" rel="external nofollow" target="_blank">CC BY-NC-SA 3.0</a> 许可协议。转载请注明出处！
  </li>
</ul>

      </div>
    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/blog/tags/JVM调优/" rel="tag"><i class="fa fa-tag"></i> JVM调优</a>
          
            <a href="/blog/tags/JVM参数/" rel="tag"><i class="fa fa-tag"></i> JVM参数</a>
          
            <a href="/blog/tags/JVM/" rel="tag"><i class="fa fa-tag"></i> JVM</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/blog/Java_reference.html" rel="next" title="Java的四种引用方式">
                <i class="fa fa-chevron-left"></i> Java的四种引用方式
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/blog/Redis_structure.html" rel="prev" title="Redis数据结构与对象">
                Redis数据结构与对象 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/blog/images/head.jpg" alt="liuchao">
            
              <p class="site-author-name" itemprop="name">liuchao</p>
              <p class="site-description motion-element" itemprop="description">好记性不如烂笔头，记下来，迈出去</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/blog/archives/">
              
                  <span class="site-state-item-count">62</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/blog/categories/index.html">
                  <span class="site-state-item-count">12</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                
                  <span class="site-state-item-count">83</span>
                  <span class="site-state-item-name">标签</span>
                
              </div>
            

          </nav>

          

          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-PrintFlagsFinal-and-XX-PrintFlagsInitial"><span class="nav-number">1.</span> <span class="nav-text">-XX:+PrintFlagsFinal and -XX:+PrintFlagsInitial</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-PrintCommandLineFlags"><span class="nav-number">2.</span> <span class="nav-text">-XX:+PrintCommandLineFlags</span></a></li></ol><li class="nav-item nav-level-3"><a class="nav-link" href="#内存调优"><span class="nav-number"></span> <span class="nav-text">内存调优</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#Xms-and-Xmx-or-XX-InitialHeapSize-and-XX-MaxHeapSize"><span class="nav-number">1.</span> <span class="nav-text">-Xms and -Xmx (or: -XX:InitialHeapSize and -XX:MaxHeapSize)</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-HeapDumpOnOutOfMemoryError-and-XX-HeapDumpPath"><span class="nav-number">2.</span> <span class="nav-text">-XX:+HeapDumpOnOutOfMemoryError and -XX:HeapDumpPath</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-OnOutOfMemoryError"><span class="nav-number">3.</span> <span class="nav-text">-XX:OnOutOfMemoryError</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-PermSize-and-XX-MaxPermSize"><span class="nav-number">4.</span> <span class="nav-text">-XX:PermSize and -XX:MaxPermSize</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-InitialCodeCacheSize-and-XX-ReservedCodeCacheSize"><span class="nav-number">5.</span> <span class="nav-text">-XX:InitialCodeCacheSize and -XX:ReservedCodeCacheSize</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-UseCodeCacheFlushing"><span class="nav-number">6.</span> <span class="nav-text">-XX:+UseCodeCacheFlushing</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#新生代垃圾回收"><span class="nav-number"></span> <span class="nav-text">新生代垃圾回收</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#Xmn"><span class="nav-number">1.</span> <span class="nav-text">-Xmn</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-NewSize-and-XX-MaxNewSize"><span class="nav-number">2.</span> <span class="nav-text">-XX:NewSize and -XX:MaxNewSize</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-NewRatio"><span class="nav-number">3.</span> <span class="nav-text">-XX:NewRatio</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-SurvivorRatio"><span class="nav-number">4.</span> <span class="nav-text">-XX:SurvivorRatio</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-PrintTenuringDistribution"><span class="nav-number">5.</span> <span class="nav-text">-XX:+PrintTenuringDistribution</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-InitialTenuringThreshold-XX-MaxTenuringThreshold-and-XX-TargetSurvivorRatio"><span class="nav-number">6.</span> <span class="nav-text">-XX:InitialTenuringThreshold, -XX:MaxTenuringThreshold and -XX:TargetSurvivorRatio</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-NeverTenure-and-XX-AlwaysTenure"><span class="nav-number">7.</span> <span class="nav-text">-XX:+NeverTenure and -XX:+AlwaysTenure</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#指定垃圾收集器"><span class="nav-number"></span> <span class="nav-text">指定垃圾收集器</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-UseSerialGC"><span class="nav-number">1.</span> <span class="nav-text">-XX:+UseSerialGC</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-UseParallelGC"><span class="nav-number">2.</span> <span class="nav-text">-XX:+UseParallelGC</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-UseParallelOldGC"><span class="nav-number">3.</span> <span class="nav-text">-XX:+UseParallelOldGC</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-ParallelGCThreads"><span class="nav-number">4.</span> <span class="nav-text">-XX:ParallelGCThreads</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#并行收集器设置"><span class="nav-number">5.</span> <span class="nav-text">并行收集器设置</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-GCTimeRatio"><span class="nav-number">6.</span> <span class="nav-text">-XX:GCTimeRatio</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#XX-MaxGCPauseMillis"><span class="nav-number">7.</span> <span class="nav-text">-XX:MaxGCPauseMillis</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#总结"><span class="nav-number"></span> <span class="nav-text">总结</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#年轻代大小选择"><span class="nav-number">1.</span> <span class="nav-text">年轻代大小选择</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#年老代大小选择"><span class="nav-number">2.</span> <span class="nav-text">年老代大小选择</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#响应时间优先的应用"><span class="nav-number">2.1.</span> <span class="nav-text">响应时间优先的应用</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#吞吐量优先的应用"><span class="nav-number">2.2.</span> <span class="nav-text">吞吐量优先的应用</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#较小堆引起的碎片问题"><span class="nav-number">2.3.</span> <span class="nav-text">较小堆引起的碎片问题</span></a></li></ol></li></ol></li></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; 2017 &mdash; <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-id-card"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">liuchao</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Mist</a></div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/blog/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/blog/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/blog/js/src/motion.js?v=5.1.4"></script>



  
  

  
  <script type="text/javascript" src="/blog/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/blog/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/blog/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  

  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    var isXml = true;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length === 0) {
      search_path = "search.xml";
    } else if (/json$/i.test(search_path)) {
      isXml = false;
    }
    var path = "/blog/" + search_path;
    // monitor main search box;

    var onPopupClose = function (e) {
      $('.popup').hide();
      $('#local-search-input').val('');
      $('.search-result-list').remove();
      $('#no-result').remove();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    }

    function proceedsearch() {
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
        .css('overflow', 'hidden');
      $('.search-popup-overlay').click(onPopupClose);
      $('.popup').toggle();
      var $localSearchInput = $('#local-search-input');
      $localSearchInput.attr("autocapitalize", "none");
      $localSearchInput.attr("autocorrect", "off");
      $localSearchInput.focus();
    }

    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';

      // start loading animation
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay">' +
          '<div id="search-loading-icon">' +
          '<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
          '</div>' +
          '</div>')
        .css('overflow', 'hidden');
      $("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');

      $.ajax({
        url: path,
        dataType: isXml ? "xml" : "json",
        async: true,
        success: function(res) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = isXml ? $("entry", res).map(function() {
            return {
              title: $("title", this).text(),
              content: $("content",this).text(),
              url: $("url" , this).text()
            };
          }).get() : res;
          var input = document.getElementById(search_id);
          var resultContent = document.getElementById(content_id);
          var inputEventFunction = function() {
            var searchText = input.value.trim().toLowerCase();
            var keywords = searchText.split(/[\s\-]+/);
            if (keywords.length > 1) {
              keywords.push(searchText);
            }
            var resultItems = [];
            if (searchText.length > 0) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var hitCount = 0;
                var searchTextCount = 0;
                var title = data.title.trim();
                var titleInLowerCase = title.toLowerCase();
                var content = data.content.trim().replace(/<[^>]+>/g,"");
                var contentInLowerCase = content.toLowerCase();
                var articleUrl = decodeURIComponent(data.url);
                var indexOfTitle = [];
                var indexOfContent = [];
                // only match articles with not empty titles
                if(title != '') {
                  keywords.forEach(function(keyword) {
                    function getIndexByWord(word, text, caseSensitive) {
                      var wordLen = word.length;
                      if (wordLen === 0) {
                        return [];
                      }
                      var startPosition = 0, position = [], index = [];
                      if (!caseSensitive) {
                        text = text.toLowerCase();
                        word = word.toLowerCase();
                      }
                      while ((position = text.indexOf(word, startPosition)) > -1) {
                        index.push({position: position, word: word});
                        startPosition = position + wordLen;
                      }
                      return index;
                    }

                    indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
                    indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
                  });
                  if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
                    isMatch = true;
                    hitCount = indexOfTitle.length + indexOfContent.length;
                  }
                }

                // show search results

                if (isMatch) {
                  // sort index by position of keyword

                  [indexOfTitle, indexOfContent].forEach(function (index) {
                    index.sort(function (itemLeft, itemRight) {
                      if (itemRight.position !== itemLeft.position) {
                        return itemRight.position - itemLeft.position;
                      } else {
                        return itemLeft.word.length - itemRight.word.length;
                      }
                    });
                  });

                  // merge hits into slices

                  function mergeIntoSlice(text, start, end, index) {
                    var item = index[index.length - 1];
                    var position = item.position;
                    var word = item.word;
                    var hits = [];
                    var searchTextCountInSlice = 0;
                    while (position + word.length <= end && index.length != 0) {
                      if (word === searchText) {
                        searchTextCountInSlice++;
                      }
                      hits.push({position: position, length: word.length});
                      var wordEnd = position + word.length;

                      // move to next position of hit

                      index.pop();
                      while (index.length != 0) {
                        item = index[index.length - 1];
                        position = item.position;
                        word = item.word;
                        if (wordEnd > position) {
                          index.pop();
                        } else {
                          break;
                        }
                      }
                    }
                    searchTextCount += searchTextCountInSlice;
                    return {
                      hits: hits,
                      start: start,
                      end: end,
                      searchTextCount: searchTextCountInSlice
                    };
                  }

                  var slicesOfTitle = [];
                  if (indexOfTitle.length != 0) {
                    slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
                  }

                  var slicesOfContent = [];
                  while (indexOfContent.length != 0) {
                    var item = indexOfContent[indexOfContent.length - 1];
                    var position = item.position;
                    var word = item.word;
                    // cut out 100 characters
                    var start = position - 20;
                    var end = position + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if (end < position + word.length) {
                      end = position + word.length;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
                  }

                  // sort slices in content by search text's count and hits' count

                  slicesOfContent.sort(function (sliceLeft, sliceRight) {
                    if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
                      return sliceRight.searchTextCount - sliceLeft.searchTextCount;
                    } else if (sliceLeft.hits.length !== sliceRight.hits.length) {
                      return sliceRight.hits.length - sliceLeft.hits.length;
                    } else {
                      return sliceLeft.start - sliceRight.start;
                    }
                  });

                  // select top N slices in content

                  var upperBound = parseInt('1');
                  if (upperBound >= 0) {
                    slicesOfContent = slicesOfContent.slice(0, upperBound);
                  }

                  // highlight title and content

                  function highlightKeyword(text, slice) {
                    var result = '';
                    var prevEnd = slice.start;
                    slice.hits.forEach(function (hit) {
                      result += text.substring(prevEnd, hit.position);
                      var end = hit.position + hit.length;
                      result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
                      prevEnd = end;
                    });
                    result += text.substring(prevEnd, slice.end);
                    return result;
                  }

                  var resultItem = '';

                  if (slicesOfTitle.length != 0) {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
                  } else {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
                  }

                  slicesOfContent.forEach(function (slice) {
                    resultItem += "<a href='" + articleUrl + "'>" +
                      "<p class=\"search-result\">" + highlightKeyword(content, slice) +
                      "...</p>" + "</a>";
                  });

                  resultItem += "</li>";
                  resultItems.push({
                    item: resultItem,
                    searchTextCount: searchTextCount,
                    hitCount: hitCount,
                    id: resultItems.length
                  });
                }
              })
            };
            if (keywords.length === 1 && keywords[0] === "") {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
            } else if (resultItems.length === 0) {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
            } else {
              resultItems.sort(function (resultLeft, resultRight) {
                if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
                  return resultRight.searchTextCount - resultLeft.searchTextCount;
                } else if (resultLeft.hitCount !== resultRight.hitCount) {
                  return resultRight.hitCount - resultLeft.hitCount;
                } else {
                  return resultRight.id - resultLeft.id;
                }
              });
              var searchResultList = '<ul class=\"search-result-list\">';
              resultItems.forEach(function (result) {
                searchResultList += result.item;
              })
              searchResultList += "</ul>";
              resultContent.innerHTML = searchResultList;
            }
          }

          if ('auto' === 'auto') {
            input.addEventListener('input', inputEventFunction);
          } else {
            $('.search-icon').click(inputEventFunction);
            input.addEventListener('keypress', function (event) {
              if (event.keyCode === 13) {
                inputEventFunction();
              }
            });
          }

          // remove loading animation
          $(".local-search-pop-overlay").remove();
          $('body').css('overflow', '');

          proceedsearch();
        }
      });
    }

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched === false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(onPopupClose);
    $('.popup').click(function(e){
      e.stopPropagation();
    });
    $(document).on('keyup', function (event) {
      var shouldDismissSearchPopup = event.which === 27 &&
        $('.search-popup').is(':visible');
      if (shouldDismissSearchPopup) {
        onPopupClose();
      }
    });
  </script>





  

  

  

  
  

  

  

  

</body>
</html>
<!-- 页面点击小红心 -->
<script type="text/javascript">
  !function(e,t,a){function n(){c(".heart{width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: fixed;}.heart:after{top: -5px;}.heart:before{left: -5px;}"),o(),r()}function r(){for(var e=0;e<d.length;e++)d[e].alpha<=0?(t.body.removeChild(d[e].el),d.splice(e,1)):(d[e].y--,d[e].scale+=.004,d[e].alpha-=.013,d[e].el.style.cssText="left:"+d[e].x+"px;top:"+d[e].y+"px;opacity:"+d[e].alpha+";transform:scale("+d[e].scale+","+d[e].scale+") rotate(45deg);background:"+d[e].color+";z-index:99999");requestAnimationFrame(r)}function o(){var t="function"==typeof e.onclick&&e.onclick;e.onclick=function(e){t&&t(),i(e)}}function i(e){var a=t.createElement("div");a.className="heart",d.push({el:a,x:e.clientX-5,y:e.clientY-5,scale:1,alpha:1,color:s()}),t.body.appendChild(a)}function c(e){var a=t.createElement("style");a.type="text/css";try{a.appendChild(t.createTextNode(e))}catch(t){a.styleSheet.cssText=e}t.getElementsByTagName("head")[0].appendChild(a)}function s(){return"rgb("+~~(255*Math.random())+","+~~(255*Math.random())+","+~~(255*Math.random())+")"}var d=[];e.requestAnimationFrame=function(){return e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame||e.msRequestAnimationFrame||function(e){setTimeout(e,1e3/60)}}(),n()}(window,document);
</script>
